#ifndef DBGPRINT_H
#define DBGPRINT_H

#include <iostream>
#include <string>

#ifndef DBGPRINT_MAX_SIZE
#define DBGPRINT_MAX_SIZE 10
#endif

#include <boost/preprocessor/repetition.hpp>
#include <boost/preprocessor/arithmetic/sub.hpp>
#include <boost/preprocessor/punctuation/comma_if.hpp>
#include <boost/preprocessor/cat.hpp>

namespace dbgprint{
inline void mark(::std::string m = "*", std::ostream& out = ::std::cout){out << m;}

#define DBGPRINT_out(z, n, data) << x ## n << delim

#define DBGPRINT_print(z, n, data) data

#define DBGPRINT_size(z, n, unused)                                     \
  template <BOOST_PP_ENUM_PARAMS(n, class T)>                           \
  inline void print_terminal                                            \
(                                                                       \
	::std::ostream& os,						\
        BOOST_PP_ENUM_BINARY_PARAMS(n, T, x),                           \
        ::std::string delim,                    		        \
	::std::string terminal						\
)                                                                       \
{                                                                       \
	os								\
                BOOST_PP_REPEAT(BOOST_PP_SUB(n,1), DBGPRINT_out, ~)     \
                << BOOST_PP_CAT(x, BOOST_PP_SUB(n,1))                   \
		<< terminal						\
        ;                                                               \
}

#include <boost/preprocessor/iteration/local.hpp>

#define BOOST_PP_LOCAL_MACRO(n)   DBGPRINT_size(~, n, ~)
#define BOOST_PP_LOCAL_LIMITS     (1, DBGPRINT_MAX_SIZE - 1)
#include BOOST_PP_LOCAL_ITERATE()

#undef DBGPRINT_size
#undef DBGPRINT_print
#undef DBGPRINT_out 
}


//Shortcuts
#define println(...)\
	print_terminal(::std::cout,__VA_ARGS__," ","\n");

#define print(...)\
	print_terminal(::std::cout,__VA_ARGS__," ","");

#define dump(x)\
	print_terminal(::std::cout,"[",__FILE__,",",__LINE__,"] ",#x,"=",x,"","\n");


#define println_err(...)\
	print_terminal(::std::cerr,__VA_ARGS__," ","\n");

#define print_err(...)\
	print_terminal(::std::cerr,__VA_ARGS__," ","");

#define dump_err(x)\
	print_terminal(::std::cerr,"[",__FILE__,",",__LINE__,"] ",#x,"=",x,"","\n");

#endif

